﻿using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.Math;
using DocumentFormat.OpenXml.Office2013.Excel;
using DocumentFormat.OpenXml.Vml.Office;
using HslCommunication;
using HslCommunication.Profinet.OpenProtocol;
using log4net.Core;
using OfficeOpenXml.Drawing.Slicer.Style;
using SiliconSelect.Base;
using SiliconSelect.BLL;
using SiliconSelect.Common;
using SiliconSelect.DAL;
using SiliconSelect.DAL.DataEntity;
using SiliconSelect.Models;
using SiliconSelect.PlcComunication;
using SiliconSelect.ViewModels;
using SiliconSelect.Views.UserOperatorDialog;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Xml.Schema;

namespace SiliconSelect.Views
{
    /// <summary>
    /// MainView.xaml 的交互逻辑
    /// </summary>
    public partial class MainView : Window
    {
        MainViewModel mainViewMod = new MainViewModel();
        public MainView()
        {
            InitializeComponent();
            // 最大化的时候不遮挡下面的任务栏的逻辑
            //MaxHeight = SystemParameters.PrimaryScreenHeight;
            WindowState = WindowState == WindowState.Maximized ?
                WindowState.Normal : WindowState.Maximized;
            DataContext = mainViewMod;
            // 1. 数据更新异步任务开启
            Loaded += AsyncTaskStart;
            // 2. 上电初始化的指令
            DeviceOperate = new Command(DoDeviceOperateTask);
            // 3. 自动作业结束的命名
            StopWorkCommand = new Command(DoStopWorkCommond);
            // 4. 关闭从站的命令(主站主动的关闭和从站通信的服务)
            CloseSlaveServerCommand = new Command(DoCloseSlaveServerCommand);
            // 5. 从新打开和从站进行通信的服务
            OpenSlaveServerCommand = new Command(DoOpenSlaveServerCommand);
            // 7. 窗体大小改变的时候,去改变显示的字体以及宽和高
            this.SizeChanged += MainWindowSizeChanged;


            // 8. 工单切换按钮
            NextCrystalPrepareCommand = new Command(DoNextCrystalPrepareTask);
            ChangeNextCrystalCommand = new Command(DoChangeNextCrystalTask);

            // 9. 3D标定按钮点击之后的逻辑
            Calibration3DCommand = new Command(Do3DCalibrationTask);

            // 10. 晶棒统计按钮
            CrystalCurrentRadioCommand = new Command(DoSwitchCrystalShowTask);

            // 11. 补偿值加载
            new VisionOffsetViewModel();
        }



        private void MainWindowSizeChanged(object sender, SizeChangedEventArgs e)
        {
            // 窗体变化的时候,去更改字体啊,或者是显示的窗口的大小.
            mainViewMod.BoxHeight = Convert.ToInt32(0.027 * ActualHeight);
            mainViewMod.BoxWidth = Convert.ToInt32(0.05 * ActualWidth);
            mainViewMod.FontBoxSmall = Convert.ToInt32(ActualHeight * 0.012);
            mainViewMod.FontBoxBig = Convert.ToInt32(ActualHeight * 0.015);
            mainViewMod.LineWidth = Convert.ToInt32(3.35 * mainViewMod.BoxWidth); // 线体宽度自适应,目前屏幕大的时候有点长
            mainViewMod.LineHeight = Convert.ToInt32(0.005 * ActualHeight);
            mainViewMod.BoardWidth = Convert.ToInt32(ActualWidth * 0.015);
            mainViewMod.BoardHeight = Convert.ToInt32(ActualHeight * 0.05);
            mainViewMod.BoardRadiusVal = Convert.ToInt32(mainViewMod.BoardWidth / 2);
            mainViewMod.RadioButtonFont = Convert.ToInt32(ActualWidth * 0.02);
            mainViewMod.RadioButtonTextFont = Convert.ToInt32(mainViewMod.RadioButtonFont * 0.8);
        }

        /// <summary>
        ///  窗口关闭的时候做一些处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void WindowClosing_Dispose()
        {
            LogHelper.WriteLog(LogType.Info, "窗口关闭,取消各个任务");
            server01?.StopServerAsync();
            _tokenSocketThread01.Cancel();
            _tokenStartServerTask01.Cancel();

            _tokenSocketThread02.Cancel();
            _tokenStartServerTask02.Cancel();
            server02?.StopServerAsync();

            _tokenSocketThread03.Cancel();
            _tokenStartServerTask03.Cancel();
            server03?.StopServerAsync();

            _tokenSocketThread04.Cancel();
            _tokenStartServerTask04.Cancel();
            server04?.StopServerAsync();


            _tokenSocketThread05.Cancel();
            _tokenStartServerTask05.Cancel();
            server05?.StopServerAsync();




            _tokenNapons.Cancel();
            NaponsClient?.StopClient();

            // 分选线程
            _tokenSelectedThread.Cancel();
            _tokenStartSelectedTask.Cancel();

            // PLC监听任务结束
            _tokenPlcThread.Cancel();
            _tokenStartPlcClient.Cancel();

            // 关闭更新数据任务
            _isRunningUpdateViewMod = false;
            _tokenUpdateViewMod!.Cancel();

            // 关闭日志清理任务
            LogHelper.clearLogToken.Cancel();
            Task task = Task.Factory.StartNew(async () =>
            {
                await Task.Delay(1000);
                ProcessManager.KillProcessByPort(GlobalValues.PcAddrList);
                await Task.Delay(500);
                Application.Current.Shutdown();
                Environment.Exit(0);
            });
        }

        /// <summary>
        /// 打开从站服务器的命令
        /// </summary>
        public Command? OpenSlaveServerCommand { get; set; }
        /// <summary>
        /// 打开从站的Server
        /// </summary>
        /// <param name="obj"></param>
        private void DoOpenSlaveServerCommand(object obj)
        {
            switch (mainViewMod.SlaveNameSelectedIndex)
            {
                case 0:
                    if (_tokenStartServerTask01.IsCancellationRequested)
                    {
                        _tokenStartServerTask01 = new CancellationTokenSource();
                    }
                    break;
                case 1:
                    if (_tokenStartServerTask02.IsCancellationRequested)
                    {
                        _tokenStartServerTask02 = new CancellationTokenSource();
                    }
                    break;
                case 2:
                    if (_tokenStartServerTask03.IsCancellationRequested)
                    {
                        _tokenStartServerTask03 = new CancellationTokenSource();
                    }
                    break;
                case 3:
                    if (_tokenStartServerTask04.IsCancellationRequested)
                    {
                        _tokenStartServerTask04 = new CancellationTokenSource();
                    }
                    break;
                case 4:
                    if (_tokenStartServerTask05.IsCancellationRequested)
                    {
                        _tokenStartServerTask05 = new CancellationTokenSource();
                    }
                    break;
            }
        }

        /// <summary>
        /// 主要关闭连接就是要关闭这个线程.如果关闭这个线程呢. 
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void DoCloseSlaveServerCommand(object obj)
        {
            // 第一步先是判断是哪一个模块,根据Index,分为1,2,3,4,5,6.
            // 六个从站(实际上只有4个)
            // 根据SlaveIndex去判断,SalveIndex从0开始的
            switch (mainViewMod.SlaveNameSelectedIndex)
            {
                case 0:
                    _tokenStartServerTask01.Cancel();
                    server01?.StopServerAsync();
                    break;
                case 1:
                    _tokenStartServerTask02.Cancel();
                    server02?.StopServerAsync();
                    break;
                case 2:
                    _tokenStartServerTask03.Cancel();
                    server03?.StopServerAsync();
                    break;
                case 3:
                    _tokenStartServerTask04.Cancel();
                    server04?.StopServerAsync();
                    break;
                case 4:
                    _tokenStartServerTask05.Cancel();
                    server05?.StopServerAsync();
                    break;
            }
        }

        /// <summary>
        /// 自动作业开始的命令
        /// </summary>
        public Command? DeviceOperate { get; set; }
        /// <summary>
        /// 设备操作的指令.上电初始化.
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void DoDeviceOperateTask(object obj)
        {
            if (obj != null)
            {
                switch (obj.ToString())
                {
                    case "InitData":
                        var res = MessageBox.Show("上电初始化用来软件掉线开启时使用,作业过程中禁止使用!", "上电初始化操作提示", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
                        if (res == MessageBoxResult.OK)
                        {
                            PowerOnDataInit();
                        }
                        break;
                    case "3DCalibration":
                        var res2 = MessageBox.Show("确定要进行3D标定吗?", "3D标定确认框", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
                        if (res2 == MessageBoxResult.OK)
                        {
                            Do3DCalibrationTask(obj);
                        }
                        break;

                    case "ChangeRecipe":
                        if (mainViewMod.RecipeComboxCanUse)
                        {
                            // 如果按钮是可用状态
                            // 先更换工单的名称
                            GlobalValues.ProductionRecipeName = mainViewMod.SelectedRecipe!;
                            List<string> updateFields = new List<string>()
                            {
                                "ProductionRecipe"
                            };
                            List<string> updateVals = new List<string>()
                            {
                                mainViewMod.SelectedRecipe!
                            };
                            DataResult result = LocalDataAccess.UpdateWorkingInfo(updateFields, updateVals);
                            if (!result.State)
                            {
                                MessageBox.Show($"数据库操作失败: {result.Message}", "数据库操作失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                                return;
                            }
                            mainViewMod.InitRecipe();
                            mainViewMod.RecipeComboxCanUse = false; // 编辑配方设置为false.
                        }
                        else
                        {
                            // 切换配方,先弹窗确认一下是否具有权限
                            PermissionCheck permissionCheck = new PermissionCheck();
                            bool? checkRes = permissionCheck.ShowDialog();
                            if (checkRes.HasValue && checkRes.Value)
                            {
                                // 如果返回True,就证明权限认证通过了,然后加载所有的配方文件,并且将配方下拉菜单该为可以编辑状态
                                mainViewMod.RecipeDirReload();
                                mainViewMod.RecipeComboxCanUse = true; // 可以使用状态
                            }
                        }
                        break;
                    case "ResetCount":
                        // 重置数据
                        DataResult resPlc = PlcClient.ResetTotalWaferCountFromPlc();
                        if (!resPlc.State)
                        {
                            LogHelper.WriteLog(LogType.Exception, resPlc.Message);
                        }

                        DataResult sqlRes = LocalDataAccess.UpdateWorkingInfo(new List<string>() { "TotalCountFromPc" }, new List<string>() { "0" });
                        if (!sqlRes.State)
                        {
                            LogHelper.WriteLog(LogType.Exception, sqlRes.Message);
                        }
                        break;

                    case "Run":
                        if (PlcClient.PlcState.IsOnline != "已连接")
                        {
                            MessageBox.Show("Plc不在线,请检查PLC是否在线以及网线是否完好", "Plc掉线提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                        else
                        {
                            DataResult runRes = PlcClient.PlcMainLineControl("mainRun");
                            if (!runRes.State)
                            {
                                MessageBox.Show($"{runRes.Message}", "Plc通信异常提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                            }
                        }
                        break;
                    case "Stop":
                        if (PlcClient.PlcState.IsOnline != "已连接")
                        {
                            MessageBox.Show("Plc不在线,请检查PLC是否在线以及网线是否完好", "Plc掉线提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                        DataResult stopRes = PlcClient.PlcMainLineControl("mainStop");
                        if (!stopRes.State)
                        {
                            MessageBox.Show($"{stopRes.Message}", "Plc通信异常提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                        break;
                    case "Clear":
                        if (PlcClient.PlcState.IsOnline != "已连接")
                        {
                            MessageBox.Show("Plc不在线,请检查PLC是否在线以及网线是否完好", "Plc掉线提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                        if (mainViewMod.CvButtonName == "CV清洗")
                        {
                            DataResult cvRes = PlcClient.PlcBeltClear("cvRun");
                            if (!cvRes.State)
                            {
                                MessageBox.Show($"{cvRes.Message}", "Plc通信异常提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                            }
                            else
                            {
                                mainViewMod.CvButtonName = "结束清洗";
                            }
                        }
                        else
                        {
                            DataResult cvRes = PlcClient.PlcBeltClear("cvStop");
                            if (!cvRes.State)
                            {
                                MessageBox.Show($"{cvRes.Message}", "Plc通信异常提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                            }
                            else
                            {
                                mainViewMod.CvButtonName = "CV清洗";
                            }
                        }
                        break;
                    case "LoadOp":
                        if (PlcClient.PlcState.IsOnline != "已连接")
                        {
                            MessageBox.Show("Plc不在线,请检查PLC是否在线以及网线是否完好", "Plc掉线提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                        string command;
                        if (mainViewMod.LoadIsOpen)
                        {
                            command = "Open";
                        }
                        else
                        {
                            command = "Close";
                        }
                        DataResult loadRes = PlcClient.PlcLoadControl(command);
                        if (!loadRes.State)
                        {
                            MessageBox.Show($"{loadRes.Message}", "Plc通信异常提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                        break;
                }
            }
        }

        /// <summary>
        /// 上电初始化
        /// </summary>
        private DataResult PowerOnDataInit()
        {
            GlobalValues.WaferIdLevelDictionary.Clear();
            GlobalValues.WaferIdFromPcDictionary.Clear();
            GlobalValues.WaferIdDateSummary.Clear();
            GlobalValues.WaferIdQueue.Clear();
            GlobalValues.ResistivityValMap.Clear();
            GlobalValues.WaferDataComman.Clear();
            GlobalValues.WaferData3d01.Clear();
            GlobalValues.WaferData3D02.Clear();
            GlobalValues.WaferDataResistivity.Clear();
            GlobalValues.WaferDataSize.Clear();
            GlobalValues.WaferDataEdgeBreak.Clear();
            GlobalValues.WaferDataSumdge.Clear();
            GlobalValues.WaferDataSubfissure.Clear();
            GlobalValues.VisionErrorWithWaferId.Clear(); // 视觉自定义异常清空.
            GlobalValues.NaponsResistivityQueue.Clear(); // Napons电阻率队列清空

            PlcClient.ResetResistivityWaferId(); // 重置电阻率流水号.
            GlobalValues.LastResistivityId = 0; // 将上一个电阻率的流水号也清空,这里不能清空,因为这里如果清空,PLC那边没有清空,还是检测到了变化就有问题.

            DataResult result = new DataResult();
            // 先弹出来进度条窗口
            server02!.ClearResponseIsOk = false;
            server03!.ClearResponseIsOk = false;
            server04!.ClearResponseIsOk = false;
            server05!.ClearResponseIsOk = false;
            DataInitProgressBar initBar = new DataInitProgressBar(SendClearQueueToAll, RefreshProcessValue);
            initBar.ShowDialog(); // 显示进度条窗口
            var task = Task.Run(async delegate
            {
                await Task.Delay(1000);
            });

            // 最后判断一下,是否有设备不在线,或者是没有连接成功的情况.
            string ErrorHappened = ""; // 是否有异常发生
            if (!mainViewMod.ModuleShieldedList.Contains("尺寸") && !server02!.ClearResponseIsOk)
            {
                ErrorHappened += "尺寸数据初始化失败,请确认尺寸工位连接状态和通信状态.  ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("前崩") && !server03!.ClearResponseIsOk)
            {
                ErrorHappened += "前崩数据初始化失败,请确认前崩工位连接状态和通信状态. ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("3D") && !server04!.ClearResponseIsOk)
            {
                ErrorHappened += "3D数据初始化失败,请确认3D工位连接状态和通信状态. ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("上脏污") && !server05!.ClearResponseIsOk)
            {
                ErrorHappened += "下脏污数据初始化失败,请确认上脏污工位连接状态和通信状态. ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("隐裂"))
            {
                ErrorHappened += "隐裂数据初始化失败,请确认隐裂工位连接状态和通信状态. ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("下脏污"))
            {
                ErrorHappened += "下脏污数据初始化失败,请确认下脏污工位连接状态和通信状态. ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("后崩"))
            {
                ErrorHappened += "后崩数据初始化失败,请确认后崩工位连接状态和通信状态. ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("左崩"))
            {
                ErrorHappened += "左崩数据初始化失败,请确认左崩工位连接状态和通信状态. ";
            }
            if (!mainViewMod.ModuleShieldedList.Contains("右崩"))
            {
                ErrorHappened += "右崩数据初始化失败,请确认右崩工位连接状态和通信状态. ";
            }

            if (ErrorHappened != "")
            {
                // 出现了异常情况,要提示工人进行下一步操作.
                MessageBox.Show($"错误: {ErrorHappened}", "上电初始化失败", MessageBoxButton.OK, MessageBoxImage.Error);
                LogHelper.WriteLog(LogType.Fatal, $"上电初始化失败: {ErrorHappened}");
            }
            else
            {
                // 正常开始往下执行
                LogHelper.WriteLog(LogType.Info, $"上电初始化成功!");
                result.State = true;
            }
            return result;
        }

        /// <summary>
        /// 更新进度条的值
        /// </summary>
        private void RefreshProcessValue()
        {
            // 所有的工站减去屏蔽掉的工站,就是剩下的工站.
            int visionSlaveCount = mainViewMod.ModuleShieldedList.Contains("电阻率") ? mainViewMod.ModuleShieldedList.Count - 1 : mainViewMod.ModuleShieldedList.Count;
            int taskCount = 9 - visionSlaveCount;
            int perVal = (100 / taskCount + 1);
            GlobalValues.DataInitProcess = 0;
            if (server01!.ClearResponseIsOk)
            {
                GlobalValues.DataInitProcess += perVal;
            }
            if (server02!.ClearResponseIsOk)
            {
                GlobalValues.DataInitProcess += perVal;
            }
            if (server03!.ClearResponseIsOk)
            {
                GlobalValues.DataInitProcess += perVal;
            }
            if (server04!.ClearResponseIsOk)
            {
                GlobalValues.DataInitProcess += perVal;
            }
            if (server05!.ClearResponseIsOk)
            {
                GlobalValues.DataInitProcess += perVal;
            }
            //if (server06!.ClearResponseIsOk)
            //{
            //    GlobalValues.DataInitProcess += perVal;
            //}
            //if (server07!.ClearResponseIsOk)
            //{
            //    GlobalValues.DataInitProcess += perVal;
            //}
            //if (server08!.ClearResponseIsOk)
            //{
            //    GlobalValues.DataInitProcess += perVal;
            //}
            //if (server09!.ClearResponseIsOk)
            //{
            //    GlobalValues.DataInitProcess += perVal;
            //}

        }

        /// <summary>
        /// 自动作业停止的命令
        /// </summary>
        public Command? StopWorkCommand { get; set; }

        /// <summary>
        /// 关闭从站服务器的命令
        /// </summary>
        public Command? CloseSlaveServerCommand { get; set; }
        /// <summary>
        /// 自动作业结束的逻辑
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void DoStopWorkCommond(object obj)
        {
            throw new NotImplementedException();
        }


        /// <summary>
        /// 启动线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <exception cref="NotImplementedException"></exception>
        private async void AsyncTaskStart(object sender, RoutedEventArgs e)
        {

            // 1. Plc 通信模块
            Task taskPlcMonitor = StartPlcMonitor();

            // 2.  启动数据监控线程
            Task taskUpdate = StartUpdatingDataAsync();

            // 3. 创建6个线程,负责和六个从站模块进行通信获取数据.
            Task taskSocket01 = StartPcSocket01();
            Task taskSocket02 = StartPcSocket02();
            Task taskSocket03 = StartPcSocket03();
            Task taskSocket04 = StartPcSocket04();
            Task taskSocket05 = StartPcSocket05();

            // 电阻率流水号获取任务
            Task taskSocket11 = StartPcSocketNapons();

            // 分选任务
            Task taskSelected = StartSelectedThread();



            await Task.WhenAll(taskUpdate, taskSocket01, taskSocket02, taskSocket03, taskSocket04, taskSocket05,
                taskPlcMonitor, taskSocket11, taskSelected);
        }

        private CancellationTokenSource _tokenNapons = new CancellationTokenSource();
        private SocketClient? NaponsClient;
        private async Task StartPcSocketNapons()
        {
            NaponsClient = new SocketClient(mainViewMod.NaponsState);
            await NaponsClient.StartClientAsync(_tokenNapons);
            if (_tokenNapons.IsCancellationRequested)
            {
                LogHelper.WriteLog(LogType.Info, $"负责Napons 电阻率 的 SocketClient 客户端关闭,等待开启");
            }
        }

        // 0. 负责PLC通信的线程
        private CancellationTokenSource _tokenPlcThread = new CancellationTokenSource();
        private CancellationTokenSource _tokenStartPlcClient = new CancellationTokenSource();
        private PlcCommunication PlcClient = PlcCommunication.Instance;
        private async Task StartPlcMonitor()
        {
            if (_tokenPlcThread.IsCancellationRequested)
            {
                return;
            }
            while (!_tokenPlcThread.IsCancellationRequested)
            {
                await DoMonitorJob();
            }
        }

        /// <summary>
        /// 负责分选线程
        /// </summary>
        private CancellationTokenSource _tokenSelectedThread = new CancellationTokenSource();
        private CancellationTokenSource _tokenStartSelectedTask = new CancellationTokenSource();
        private async Task StartSelectedThread()
        {
            if (_tokenSelectedThread.IsCancellationRequested)
            {
                return;
            }
            while (!_tokenSelectedThread.IsCancellationRequested)
            {
                await DoSelectedJob();
            }
        }

        private async Task DoSelectedJob()
        {
            try
            {
                while (!_tokenStartSelectedTask.IsCancellationRequested)
                {
                    if (_tokenStartSelectedTask.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        break;
                    }
                    else
                    {
                        while (!_tokenStartSelectedTask.IsCancellationRequested)
                        {
                            await Task.Run(() =>
                            {
                                //// 测试写入
                                //Stopwatch sw3 = Stopwatch.StartNew();
                                //DataResult result04 = PlcCommunication.Instance.WriteBoxNumberNew(ushort.Parse("1"), 19);
                                //sw3.Stop();
                                //LogHelper.WriteLog(LogType.Info, $"流水号:{1},对应的料盒{19} 写入成功,写入耗时:{sw3.ElapsedMilliseconds} ms");
                                //await Task.Delay(1000);

                                Stopwatch sw = Stopwatch.StartNew();
                                var waferIdList = GlobalValues.WaferIdDateSummary.Keys.ToList();
                                waferIdList.Sort((x, y) => int.Parse(x).CompareTo(int.Parse(y)));
                                if (waferIdList.Count > 0)
                                {
                                    // 一次只取一个有效数据.如果都无效,就继续下一循环.
                                    string? waferId = string.Empty;
                                    DataResult msgIsOK = new DataResult();
                                    for (int i = 0; i < waferIdList.Count; i++)
                                    {
                                        DateTime waferDatetime = GlobalValues.WaferIdDateSummary[waferIdList[i]];
                                        TimeSpan timeSpan = DateTime.Now - waferDatetime;
                                        msgIsOK = ResultSummaryHelper.CheckMsgIsComplete(waferIdList[i]);
                                        if (msgIsOK.State || timeSpan.TotalSeconds >= 4)
                                        {
                                            // 如果大于等于3秒就认为是已经分选完毕了,再来也不接受数据了
                                            waferId = waferIdList[i];
                                            // 在这里清除数据
                                            if (GlobalValues.WaferIdFromPcDictionary.ContainsKey(waferId))
                                            {
                                                // 清空这个流水号的数据,不管这里数据有没有完成. 都会将数据清空.
                                                GlobalValues.WaferIdFromPcDictionary.Remove(waferId);
                                            }
                                            break;
                                        }
                                    }
                                    if (msgIsOK.Message != "电阻率误判" && msgIsOK.Message != "流水号消息缺失, 所有工位")
                                    {
                                        if (!string.IsNullOrEmpty(waferId) && waferId != "0")
                                        {
                                            GlobalValues.LastWaferId = int.Parse(waferId);
                                            GlobalValues.WaferIdDateSummary.Remove(waferId);
                                            int calcLevel = 32; // 默认是直流
                                            int boxNumber = 19;
                                            string[] waferLevelData = new string[GlobalValues.CommanTitle.Length];
                                            waferLevelData[0] = DateTimeHelper.GetTimeNowForSql();
                                            waferLevelData[1] = DateTimeHelper.GetProductionDatetime();
                                            waferLevelData[2] = waferId;
                                            waferLevelData[3] = GlobalValues.CrystalNumberCurrent!;
                                            waferLevelData[4] = GlobalValues.CrystalNumberCurrent!;
                                            waferLevelData[5] = GlobalValues.PositionNumber!;
                                            waferLevelData[6] = GlobalValues.ProductionLot!;
                                            waferLevelData[7] = GlobalValues.FlowerNumber!;
                                            waferLevelData[8] = GlobalValues.ProductionRecipeName!;
                                            waferLevelData[9] = ""; //   默认是空,汇总等级  无等级
                                            waferLevelData[10] = ""; // 等级类型         缺数直流,流水号:634,缺数据工位:
                                            waferLevelData[11] = ""; //  类型描述,        缺数工位: 
                                            waferLevelData[12] = ""; // 入选料盒(直流是19)

                                            if (msgIsOK.State) // 数据完整.
                                            {
                                                ushort waferIdToPlc = ushort.Parse(waferId);
                                                // 如果消息完整,求去根据这个消息计算它的等级.
                                                DataResult<int> levelRes = CalcLevelHelper.GetLevelResByWaferId(waferId);
                                                calcLevel = levelRes.Data;

                                                if (levelRes.State)
                                                {
                                                    if (calcLevel < 30)
                                                    {
                                                        // 已经计算出等级,然后根据等级去计算料盒.
                                                        boxNumber = CalcLevelHelper.GetBoxesNumberByLevel(calcLevel, mainViewMod.BoxesStateList);
                                                    }
                                                    else
                                                    {

                                                    }
                                                }
                                                else
                                                {
                                                    LogHelper.WriteLog(LogType.Exception, $"根据流水号获取等级计算出错: {levelRes.Data!}");
                                                }
                                            }
                                            Stopwatch sw2 = Stopwatch.StartNew();
                                            //DataResult result = PlcCommunication.Instance.WriteBoxNumber(int.Parse(waferId), boxNumber);

                                            //if (result.State)
                                            //{
                                            //    sw2.Stop();
                                            //    LogHelper.WriteLog(LogType.Info, $"流水号:{waferId},对应的料盒{boxNumber} 写入成功,写入耗时:{sw2.ElapsedMilliseconds} ms");
                                            //}
                                            //else
                                            //{
                                            //    LogHelper.WriteLog(LogType.Info, $"流水号:{waferId},对应的料盒{boxNumber} 写入失败,失败原因: {result.Message}");
                                            //}


                                            // 注意这里分两种情况,第一种是正常等级,第二个是直流.主要是看boxNumber 
                                            if (!msgIsOK.State)
                                            {

                                                // 数据不完整.
                                                LogHelper.WriteLog(LogType.Fatal, $"缺数直流,流水号: {waferId},缺数据工位:{msgIsOK.Message}", errorCode: "P08", isInsert: true);
                                                // 缺数直流
                                                LocalDataAccess.UpdateCrystalLevelCountTbLoss(GlobalValues.CrystalNumberCurrent!, 31);
                                                // 如果是缺数直流就直接写成缺数直流
                                                waferLevelData[9] = "31"; // 等级是31
                                                waferLevelData[10] = "缺数直流";
                                                waferLevelData[11] = $"缺数据工位:{msgIsOK.Message}";
                                                waferLevelData[12] = "19";
                                            }
                                            else
                                            {
                                                if (calcLevel == 0)
                                                {
                                                    waferLevelData[9] = calcLevel.ToString();
                                                    waferLevelData[10] = "直流";
                                                    waferLevelData[11] = "直流";
                                                    boxNumber = 19; // 直流
                                                }
                                                else if (calcLevel >= 30)
                                                {
                                                    boxNumber = 19;
                                                    waferLevelData[9] = calcLevel.ToString();
                                                    waferLevelData[10] = "视觉自定义错误";
                                                    if (GlobalValues.VisionErrorWithWaferId.ContainsKey(waferId))
                                                    {
                                                        waferLevelData[11] = GlobalValues.VisionErrorWithWaferId[waferId];
                                                        GlobalValues.VisionErrorWithWaferId.Remove(waferId);
                                                    }
                                                    else
                                                    {
                                                        waferLevelData[11] = GlobalValues.DetectedTypeNamesDefineSelf[calcLevel];
                                                    }
                                                }
                                                else
                                                {
                                                    RecipeConfigModel recipeConfig = GlobalValues.RecipeConfig[calcLevel - 1];
                                                    waferLevelData[9] = calcLevel.ToString();
                                                    waferLevelData[10] = recipeConfig.LevelType!;
                                                    waferLevelData[11] = recipeConfig.TypeDescription!;
                                                }
                                                waferLevelData[12] = boxNumber.ToString();


                                                if (calcLevel < 30 && calcLevel > 0 && boxNumber < 19)
                                                {
                                                    // 非直流正常等级分选更新.
                                                    DataResult result02 = LocalDataAccess.UpdateCrystalLevelCountTbNormal(GlobalValues.CrystalNumberCurrent!, calcLevel);
                                                }
                                                else
                                                {
                                                    // 这里直流,初步认定为料盒满直流,这里有两种情况如果等级是大于等于30的就保存对应等级的数量,如果小于,就不保存了,免得数据重复
                                                    // 有可能是视觉自定义错误的直流,也在这里进行.
                                                    DataResult result02 = LocalDataAccess.UpdateCrystalLevelCountDirection(GlobalValues.CrystalNumberCurrent!, calcLevel);
                                                }
                                            }

                                            // 1. 将分选的料盒写入到
                                            PlcCommunication.Instance.WriteBoxNumber(int.Parse(waferId), boxNumber);
                                            LogHelper.WriteLog(LogType.TestShow, $"分选料盒写入,流水号: {waferId}, 料盒:{boxNumber}");
                                            GlobalValues.WaferDataComman[waferId] = waferLevelData;
                                            LocalDataAccess.UpdateWorkingInfoTotalCountFromPc();
                                            DoSaveSummaryDataTask(waferId);
                                            sw.Stop();
                                            LogHelper.WriteLog(LogType.Info, $"分选耗时:{sw.ElapsedMilliseconds} ms");
                                        }
                                        else
                                        {
                                            if (!string.IsNullOrEmpty(waferId))
                                            {
                                                GlobalValues.WaferIdFromPcDictionary.Remove(waferId);
                                                GlobalValues.WaferIdDateSummary.Remove(waferId);
                                            }
                                        }
                                    }
                                    //else
                                    //{
                                    //    // 如果发现是电阻率误判,就将这条数据移除掉得了.或者是不管,不管也是可以的.
                                    //}
                                }
                            });
                            await Task.Delay(50);
                            // 后面就是做数据保存工作.

                            //Task.Run(() =>
                            //{
                            //    // 根据Ip去获取要写入到文件的字符串
                            //    List<string> strToCsv = ResultSummaryHelper.GetSummaryResList(waferId);
                            //    if (strToCsv.Count > 0)
                            //    {
                            //        CsvHelper.WriteToCsvSingleLine(GlobalValues.SummaryByDayPath, strToCsv);
                            //        CsvHelper.WriteToCsvSingleLine(GlobalValues.SummaryByCrystalNumberPath, strToCsv);
                            //    }
                            //});
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
            finally
            {
                LogHelper.WriteLog(LogType.Info, "PlcMonitorTask12 任务结束");
            }
        }



        private async Task DoMonitorJob()
        {
            try
            {

                while (!_tokenStartPlcClient.IsCancellationRequested)
                {
                    if (_tokenStartPlcClient.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        break;
                    }
                    else
                    {
                        while (!_tokenStartPlcClient.IsCancellationRequested)
                        {
                            if (PlcDisconnectdCount >= 5)
                            {
                                await Task.Delay(1000);
                                continue;
                            }
                            // 读取PLC状态
                            if (PlcClient.PlcState.IsOnline != "已连接")
                            {
                                await Task.Run(() =>
                                {
                                    PlcClient.ConnectPlc();
                                });
                                if (PlcClient.PlcState.IsOnline != "已连接")
                                {
                                    PlcDisconnectdCount++;
                                    await Task.Delay(1000);
                                    continue;
                                }
                            }
                            await Task.Run(async () =>
                            {
                                DataResult<int> res2 = PlcClient.GetWaferIdForResistivity();
                                if (res2.State)
                                {
                                    int waferIdFromPlc = res2.Data!;
                                    // -1 表示程序刚启动,这个时候就不要去做比较了. 如果是小于等于就不要了.肯定是错误的.
                                    // 流水号要大于上一个流水号才会认为是有效值.并且上一个流水号
                                    //LogHelper.WriteLog(LogType.Info, $"读取电阻率流水号: {waferIdFromPlc}");
                                    if (waferIdFromPlc > GlobalValues.LastResistivityId && waferIdFromPlc != 0)
                                    {
                                        GlobalValues.LastResistivityId = res2.Data!;
                                        LogHelper.WriteLog(LogType.Info, $"获取电阻率触发信号,读取对应流水号: {waferIdFromPlc}");
                                        GlobalValues.WaferIdQueue.Enqueue(res2.Data!.ToString());
                                        //int boxNumber = 1;
                                        //// 测试料盒写入
                                        //if (mainViewMod.IsFixedBox)
                                        //{
                                        //    // 随机料盒
                                        //    boxNumber = RandomHelper.GetRandomInt(1, 19);
                                        //}
                                        //else
                                        //{
                                        //    boxNumber = mainViewMod.BoxInto;
                                        //}
                                        //PlcCommunication.Instance.WriteBoxNumber(waferIdFromPlc, boxNumber);
                                        //LogHelper.WriteLog(LogType.TestShow, $"测试分选料盒写入,流水号: {waferIdFromPlc}, 料盒:{boxNumber}");
                                    }
                                }
                                await Task.Delay(10); // 休眠5ms
                                //// 测试写入流水号和料盒
                                //int waferId = RandomHelper.GetRandomInt(100, 110);
                                //int boxNumber = RandomHelper.GetRandomInt(1, 18);
                                //PlcCommunication.Instance.WriteBoxNumber(waferId, boxNumber);
                                //LogHelper.WriteLog(LogType.TestShow, $"测试分选料盒写入,流水号: {waferId}, 料盒:{boxNumber}");
                            });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Info, $"GetWaferIdQueueTask结束,{ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!)}");
            }
        }

        /// <summary>
        /// PLC连接已断开次数
        /// </summary>
        public int PlcDisconnectdCount { get; set; }

        public int boxIntoCount = 0;



        /// <summary>
        /// 从PLC那里更新料盒状态.
        /// </summary>
        //private void UpdateBoxStateFromPlc()
        //{
        //    DataResult<List<ushort>> boxCountListRes = PlcClient.GetBoxCountsFromPlc();
        //    DataResult<bool[]> boxIsOkState = PlcClient.GetBoxIsOkState();
        //    if (boxCountListRes.State && boxIsOkState.State)
        //    {
        //        for (int i = 0; i < mainViewMod.BoxesStateList.Count; i++)
        //        {
        //            Application.Current?.Dispatcher.Invoke(() =>
        //            {
        //                mainViewMod.BoxesStateList[i].UpCount = boxCountListRes.Data![i * 2];
        //                if (i < boxIsOkState.Data?.Length && !boxIsOkState.Data![i])
        //                {
        //                    if (!boxIsOkState.Data![i])
        //                    {
        //                        // 如果料盒出现了异常,将下框赋值为异常状态.这里要报警的.
        //                        mainViewMod.BoxesStateList[i].DownBoxState = (int)BoxesStates.Locked;
        //                        LogHelper.WriteLog(LogType.Fatal, "", $"B{i + 1}"); // 料盒异常的时候,报警信息用B1 ,B2, 到 B18来提示.
        //                    }
        //                    else
        //                    {
        //                        // 如果检测到料盒气缸到位之后,就将其置位空闲.
        //                        if (mainViewMod.BoxesStateList[i].DownBoxState == (int)BoxesStates.Locked)
        //                        {
        //                            mainViewMod.BoxesStateList[i].DownBoxState = (int)BoxesStates.Free;
        //                        }
        //                    }

        //                }
        //                if (i <= mainViewMod.BoxesStateList.Count - 2)
        //                {
        //                    mainViewMod.BoxesStateList[i].DownCount = boxCountListRes.Data![2 * i + 1];
        //                }
        //                // 用来测试
        //                //mainViewMod.BoxesStateList[0].Count = i;
        //            });
        //        }
        //    }
        //    else
        //    {
        //        LogHelper.WriteLog(LogType.Warn, boxCountListRes.Message);
        //    }

        //    // 更新实际片数,总流入和总流出
        //    DataResult<List<int>> waferCountRes = PlcClient.GetTotalWaferCountFromPlc();
        //    if (waferCountRes.State)
        //    {
        //        //mainViewMod.WorkingInfo.RealCounts = waferCountRes.Data![0]; // 实际片数之前是从PLC获取,考虑到碎片情况,这里自己用自己的数据
        //        mainViewMod.WorkingInfo.RealCounts = GlobalValues.TotalWaferCount;
        //        mainViewMod.WorkingInfo.TotalCountInFromPlc = waferCountRes.Data![1]; // 总流入
        //        mainViewMod.WorkingInfo.TotalCountOutFromPlc = waferCountRes.Data![2]; // 总流出
        //        mainViewMod.Capacity = waferCountRes.Data![3].ToString(); // 产能
        //        mainViewMod.Beat = waferCountRes.Data![4].ToString(); // 节拍
        //        // 这个是本单直流片数统计,每次读取到直流片数的时候,要去数据库更新一下,然后这个值加上正常分选的
        //        // 就是总的片数.现在又改了,就是这个数据是统计的总的直流,然后,缺数直流,要根据这个直流减去其他工位的直流.
        //        // 就是说这个总直流要分开去量化.一个是总直流,一个是缺数直接和其他直流.先去算缺数直流,先按照自己的去统计
        //        //LocalDataAccess.UpdateCrystalLevelCountTbPlcDirection(GlobalValues.CrystalNumberCurrent!, waferCountRes.Data![3]);

        //        // 如果实际片数已经大于了理论片数,就弹窗提示工人进行操作.
        //        if (mainViewMod.WorkingInfo.RealCounts > 0 && mainViewMod.WorkingInfo.TheoryCounts > 0 && !GlobalValues.DialogIsVisible &&
        //            mainViewMod.WorkingInfo.RealCounts >= mainViewMod.WorkingInfo.TheoryCounts && !GlobalValues.CrystalFinishState)
        //        {
        //            // 1. 停止上料,并且弹窗
        //            DataResult plcRes = PlcClient.PlcLoadControl("Close");
        //            if (!plcRes.State)
        //            {
        //                MessageBox.Show($"PLC通信异常: {plcRes.Message}", "Plc通信异常提示框", MessageBoxButton.OK, MessageBoxImage.Error);
        //                Application.Current?.Shutdown();
        //            }

        //            Application.Current?.Dispatcher.Invoke(() =>
        //            {
        //                int theoryCount = mainViewMod.WorkingInfo.TheoryCounts;
        //                int realCount = mainViewMod.WorkingInfo.RealCounts;
        //                CrystalFinishDialog finishDialog = new CrystalFinishDialog(theoryCount, realCount);
        //                GlobalValues.DialogIsVisible = true;
        //                finishDialog.ShowDialog();
        //            });
        //        }
        //    }
        //    else
        //    {
        //        LogHelper.WriteLog(LogType.Exception, waferCountRes?.Message);
        //    }

        //}



        // 1. 第一个线程和第一个开启服务的标志位
        private CancellationTokenSource _tokenSocketThread01 = new CancellationTokenSource();
        private CancellationTokenSource _tokenStartServerTask01 = new CancellationTokenSource();
        private async Task StartPcSocket01()
        {
            if (_tokenSocketThread01.IsCancellationRequested)
            {
                return;
            }
            while (!_tokenSocketThread01.IsCancellationRequested)
            {
                await DoSocketJob01();
            }
        }

        SocketServer? server01;
        /// <summary>
        /// 具体的Socket01的通信任务.
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task DoSocketJob01()
        {
            try
            {
                while (!_tokenSocketThread01.IsCancellationRequested)
                {
                    if (_tokenStartServerTask01.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        continue;
                    }
                    else
                    {
                        server01 = new SocketServer(mainViewMod.ResistivityPcState);
                        await server01.StartServerAsync(_tokenStartServerTask01);
                        if (_tokenStartServerTask01.IsCancellationRequested)
                        {
                            LogHelper.WriteLog(LogType.Info, $"负责从站 国产电阻率 的 SocketServer 服务器关闭,等待开启");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
            finally
            {
                LogHelper.WriteLog(LogType.Info, "StartServerAsync01 Task 任务结束");
            }
        }

        // 2. 第二个线程和第二个开启服务的标志位
        private CancellationTokenSource _tokenSocketThread02 = new CancellationTokenSource();
        private CancellationTokenSource _tokenStartServerTask02 = new CancellationTokenSource();
        private async Task StartPcSocket02()
        {
            if (_tokenSocketThread02.IsCancellationRequested)
            {
                return;
            }
            while (!_tokenSocketThread02.IsCancellationRequested)
            {
                await DoSocketJob02();
            }
        }

        SocketServer? server02;
        /// <summary>
        /// 具体的Socket02的通信任务. 尺寸
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task DoSocketJob02()
        {
            try
            {
                while (!_tokenSocketThread02.IsCancellationRequested)
                {
                    if (_tokenStartServerTask02.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        continue;
                    }
                    else
                    {
                        server02 = new SocketServer(mainViewMod.SizePcState);
                        await server02.StartServerAsync(_tokenStartServerTask02);
                        if (_tokenStartServerTask02.IsCancellationRequested)
                        {
                            LogHelper.WriteLog(LogType.Info, $"负责从站 尺寸 的 SocketServer 服务器关闭,等待开启");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
            finally
            {
                LogHelper.WriteLog(LogType.Info, "StartServerAsync02 Task 任务结束");
            }
        }

        // 3. 第三个线程和第三个开启服务的标志位
        private CancellationTokenSource _tokenSocketThread03 = new CancellationTokenSource();
        private CancellationTokenSource _tokenStartServerTask03 = new CancellationTokenSource();
        private async Task StartPcSocket03()
        {
            if (_tokenSocketThread03.IsCancellationRequested)
            {
                return;
            }
            while (!_tokenSocketThread03.IsCancellationRequested)
            {
                await DoSocketJob03();
            }
        }

        SocketServer? server03;
        /// <summary>
        /// 具体的Socket03的通信任务. 崩边和隐裂
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task DoSocketJob03()
        {
            try
            {
                while (!_tokenSocketThread03.IsCancellationRequested)
                {
                    if (_tokenStartServerTask03.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        continue;
                    }
                    else
                    {
                        mainViewMod.EdgeBreakPcState.PortAdd = 0;
                        server03 = new SocketServer(mainViewMod.EdgeBreakPcState);
                        await server03.StartServerAsync(_tokenStartServerTask03);
                        if (_tokenStartServerTask03.IsCancellationRequested)
                        {
                            LogHelper.WriteLog(LogType.Info, $"负责从站 崩边隐裂 的 SocketServer 服务器关闭,等待开启");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
            finally
            {
                LogHelper.WriteLog(LogType.Info, "StartServerAsync03 Task 任务结束");
            }
        }

        // 4. 第四个线程和第四个开启服务的标志位
        private CancellationTokenSource _tokenSocketThread04 = new CancellationTokenSource();
        private CancellationTokenSource _tokenStartServerTask04 = new CancellationTokenSource();
        private async Task StartPcSocket04()
        {
            if (_tokenSocketThread04.IsCancellationRequested)
            {
                return;
            }
            while (!_tokenSocketThread04.IsCancellationRequested)
            {
                await DoSocketJob04();
            }
        }

        SocketServer? server04;
        /// <summary>
        /// 具体的Socket04的通信任务. 3D
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task DoSocketJob04()
        {
            try
            {
                while (!_tokenSocketThread04.IsCancellationRequested)
                {
                    if (_tokenStartServerTask04.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        continue;
                    }
                    else
                    {
                        server04 = new SocketServer(mainViewMod.ThicknessPcState);
                        await server04.StartServerAsync(_tokenStartServerTask04);
                        if (_tokenStartServerTask04.IsCancellationRequested)
                        {
                            LogHelper.WriteLog(LogType.Info, $"负责从站 3D 的 SocketServer 服务器关闭,等待开启");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
            finally
            {
                LogHelper.WriteLog(LogType.Info, "StartServerAsync04 Task 任务结束");
            }
        }


        // 5. 第五个线程和第五个开启服务的标志位
        private CancellationTokenSource _tokenSocketThread05 = new CancellationTokenSource();
        private CancellationTokenSource _tokenStartServerTask05 = new CancellationTokenSource();
        private async Task StartPcSocket05()
        {
            if (_tokenSocketThread05.IsCancellationRequested)
            {
                return;
            }
            while (!_tokenSocketThread05.IsCancellationRequested)
            {
                await DoSocketJob05();
            }
        }

        SocketServer? server05;
        /// <summary>
        /// 具体的Socket05的通信任务. 下脏污
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task DoSocketJob05()
        {
            try
            {
                while (!_tokenSocketThread05.IsCancellationRequested)
                {
                    if (_tokenStartServerTask05.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        continue;
                    }
                    else
                    {
                        mainViewMod.SmudgePcState.PortAdd = 0;
                        server05 = new SocketServer(mainViewMod.SmudgePcState);
                        await server05.StartServerAsync(_tokenStartServerTask05);
                        if (_tokenStartServerTask05.IsCancellationRequested)
                        {
                            LogHelper.WriteLog(LogType.Info, $"负责从站 下脏污 的 SocketServer 服务器关闭,等待开启");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
            finally
            {
                LogHelper.WriteLog(LogType.Info, "StartServerAsync05 Task 任务结束");
            }
        }

        //// 6. 第六个线程和第六个开启服务的标志位
        //private CancellationTokenSource _tokenSocketThread06 = new CancellationTokenSource();
        //private CancellationTokenSource _tokenStartServerTask06 = new CancellationTokenSource();
        //private async Task StartPcSocket06()
        //{
        //    if (_tokenSocketThread06.IsCancellationRequested)
        //    {
        //        return;
        //    }
        //    while (!_tokenSocketThread06.IsCancellationRequested)
        //    {
        //        await DoSocketJob06();
        //    }
        //}

        //SocketServer? server06;
        ///// <summary>
        ///// 具体的Socket06的通信任务. 隐裂
        ///// </summary>
        ///// <returns></returns>
        ///// <exception cref="NotImplementedException"></exception>
        //private async Task DoSocketJob06()
        //{
        //    try
        //    {
        //        while (!_tokenSocketThread06.IsCancellationRequested)
        //        {
        //            if (_tokenStartServerTask06.IsCancellationRequested)
        //            {
        //                await Task.Delay(1000);
        //                continue;
        //            }
        //            else
        //            {
        //                server06 = new SocketServer(mainViewMod.SubfissurePcState);
        //                await server06.StartServerAsync(_tokenStartServerTask06);
        //                if (_tokenStartServerTask06.IsCancellationRequested)
        //                {
        //                    LogHelper.WriteLog(LogType.Info, $"负责从站 隐裂 的 SocketServer 服务器关闭,等待开启");
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
        //    }
        //    finally
        //    {
        //        LogHelper.WriteLog(LogType.Info, "StartServerAsync06 Task 任务结束");
        //    }
        //}

        //// 7. 第7个线程 
        //private CancellationTokenSource _tokenSocketThread07 = new CancellationTokenSource();
        //private CancellationTokenSource _tokenStartServerTask07 = new CancellationTokenSource();
        //private async Task StartPcSocket07()
        //{
        //    if (_tokenSocketThread07.IsCancellationRequested)
        //    {
        //        return;
        //    }
        //    while (!_tokenSocketThread07.IsCancellationRequested)
        //    {
        //        await DoSocketJob07();
        //    }
        //}
        //SocketServer? server07; // 上脏污
        ///// <summary>
        ///// 具体的Socket07的通信任务. 另外一个脏污服务器
        ///// </summary>
        ///// <returns></returns>
        ///// <exception cref="NotImplementedException"></exception>
        //private async Task DoSocketJob07()
        //{
        //    try
        //    {
        //        while (!_tokenSocketThread07.IsCancellationRequested)
        //        {
        //            if (_tokenStartServerTask07.IsCancellationRequested)
        //            {
        //                await Task.Delay(1000);
        //                continue;
        //            }
        //            else
        //            {
        //                mainViewMod.SmudgePcState.PortAdd = 10;
        //                server07 = new SocketServer(mainViewMod.SmudgePcState);
        //                await server07.StartServerAsync(_tokenStartServerTask07);
        //                if (_tokenStartServerTask07.IsCancellationRequested)
        //                {
        //                    LogHelper.WriteLog(LogType.Info, $"负责从站 上脏污 的 SocketServer 服务器关闭,等待开启");
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
        //    }
        //    finally
        //    {
        //        LogHelper.WriteLog(LogType.Info, "StartServerAsync07 Task 任务结束");
        //    }
        //}

        //// 崩边工位 2 后崩
        //private CancellationTokenSource _tokenSocketThread08 = new CancellationTokenSource();
        //private CancellationTokenSource _tokenStartServerTask08 = new CancellationTokenSource();
        //private async Task StartPcSocket08()
        //{
        //    if (_tokenSocketThread08.IsCancellationRequested)
        //    {
        //        return;
        //    }
        //    while (!_tokenSocketThread08.IsCancellationRequested)
        //    {
        //        await DoSocketJob08();
        //    }
        //}

        //SocketServer? server08;
        ///// <summary>
        ///// 具体的Socket08的通信任务. 后崩
        ///// </summary>
        ///// <returns></returns>
        ///// <exception cref="NotImplementedException"></exception>
        //private async Task DoSocketJob08()
        //{
        //    try
        //    {
        //        while (!_tokenSocketThread08.IsCancellationRequested)
        //        {
        //            if (_tokenStartServerTask08.IsCancellationRequested)
        //            {
        //                await Task.Delay(1000);
        //                continue;
        //            }
        //            else
        //            {
        //                mainViewMod.EdgeBreakPcState.PortAdd = 10;
        //                server08 = new SocketServer(mainViewMod.EdgeBreakPcState);
        //                await server08.StartServerAsync(_tokenStartServerTask08);
        //                if (_tokenStartServerTask08.IsCancellationRequested)
        //                {
        //                    LogHelper.WriteLog(LogType.Info, $"负责从站 后崩 的 SocketServer 服务器关闭,等待开启");
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
        //    }
        //    finally
        //    {
        //        LogHelper.WriteLog(LogType.Info, "StartServerAsync08 Task 任务结束");
        //    }
        //}

        //// 崩边工位 3  左崩
        //private CancellationTokenSource _tokenSocketThread09 = new CancellationTokenSource();
        //private CancellationTokenSource _tokenStartServerTask09 = new CancellationTokenSource();
        //private async Task StartPcSocket09()
        //{
        //    if (_tokenSocketThread09.IsCancellationRequested)
        //    {
        //        return;
        //    }
        //    while (!_tokenSocketThread09.IsCancellationRequested)
        //    {
        //        await DoSocketJob09();
        //    }
        //}

        //SocketServer? server09;
        ///// <summary>
        ///// 具体的Socket09的通信任务.  左崩
        ///// </summary>
        ///// <returns></returns>
        ///// <exception cref="NotImplementedException"></exception>
        //private async Task DoSocketJob09()
        //{
        //    try
        //    {
        //        while (!_tokenSocketThread09.IsCancellationRequested)
        //        {
        //            if (_tokenStartServerTask09.IsCancellationRequested)
        //            {
        //                await Task.Delay(1000);
        //                continue;
        //            }
        //            else
        //            {
        //                mainViewMod.EdgeBreakPcState.PortAdd = 20;
        //                server09 = new SocketServer(mainViewMod.EdgeBreakPcState);
        //                await server09.StartServerAsync(_tokenStartServerTask09);
        //                if (_tokenStartServerTask09.IsCancellationRequested)
        //                {
        //                    LogHelper.WriteLog(LogType.Info, $"负责从站 左崩 的 SocketServer 服务器关闭,等待开启");
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
        //    }
        //    finally
        //    {
        //        LogHelper.WriteLog(LogType.Info, "StartServerAsync09 Task 任务结束");
        //    }
        //}

        //// 崩边隐裂工位   
        //private CancellationTokenSource _tokenSocketThread10 = new CancellationTokenSource();
        //private CancellationTokenSource _tokenStartServerTask10 = new CancellationTokenSource();
        //private async Task StartPcSocket10()
        //{
        //    if (_tokenSocketThread10.IsCancellationRequested)
        //    {
        //        return;
        //    }
        //    while (!_tokenSocketThread10.IsCancellationRequested)
        //    {
        //        await DoSocketJob10();
        //    }
        //}

        //SocketServer? server10;
        ///// <summary>
        ///// 具体的Socket10 崩边隐裂工位
        ///// </summary>
        ///// <returns></returns>
        ///// <exception cref="NotImplementedException"></exception>
        //private async Task DoSocketJob10()
        //{
        //    try
        //    {
        //        while (!_tokenSocketThread10.IsCancellationRequested)
        //        {
        //            if (_tokenStartServerTask10.IsCancellationRequested)
        //            {
        //                await Task.Delay(1000);
        //                continue;
        //            }
        //            else
        //            {
        //                mainViewMod.EdgeBreakPcState.PortAdd = 0;
        //                server10 = new SocketServer(mainViewMod.EdgeBreakPcState);
        //                await server10.StartServerAsync(_tokenStartServerTask10);
        //                if (_tokenStartServerTask10.IsCancellationRequested)
        //                {
        //                    LogHelper.WriteLog(LogType.Info, $"负责从站 崩边隐裂 的 SocketServer 服务器关闭,等待开启");
        //                }
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
        //    }
        //    finally
        //    {
        //        LogHelper.WriteLog(LogType.Info, "StartServerAsync10 Task 任务结束");
        //    }
        //}



        private bool _isRunningUpdateViewMod;
        private CancellationTokenSource? _tokenUpdateViewMod;
        public async Task StartUpdatingDataAsync()
        {
            if (_isRunningUpdateViewMod)
            {
                return;
            }
            _tokenUpdateViewMod = new CancellationTokenSource();
            _isRunningUpdateViewMod = true;

            while (_isRunningUpdateViewMod)
            {
                await Task.Delay(700);
                if (_tokenUpdateViewMod.IsCancellationRequested)
                {
                    break;
                }
                await Task.Run(() =>
                {
                    UpdateMainPageViewFromSql();
                });
                await Task.Delay(700);
                if (_tokenUpdateViewMod.IsCancellationRequested)
                {
                    break;
                }
            }
            LogHelper.WriteLog(LogType.Info, " StartUpdatingDataAsync11 任务结束");
        }

        // 保存数据任务(不管是缺数还是不缺数,都一样的保存
        private void DoSaveSummaryDataTask(string waferId)
        {
            try
            {
                List<string> writeStr = ResultSummaryHelper.GetSummaryResListFromGlobal(waferId);
                if (writeStr.Count > 0)
                {
                    // 缺数直流
                    LocalDataAccess.SaveSummaryData(writeStr);
                    CsvHelper.WriteToCsvSingleLine(GlobalValues.SummaryByCrystalNumberPath, writeStr);
                    CsvHelper.WriteToCsvSingleLine(GlobalValues.SummaryByDayPath, writeStr);
                }

            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!));
            }
        }

        /// <summary>
        /// 更新数据的任务
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private void UpdateMainPageViewFromSql()
        {
            try
            {
                // 1. WorkingInfo 数据更新
                Task.Run(() =>
                {
                    // 1. 去检测设备连接状态,如果不在线超过3次,就要报警
                    CheckDeviceIsOnline();
                    // 倒叙排列,最新的报警在最上面.
                    DataResult<List<AlarmRecordEntity>> result = LocalDataAccess.GetAlarmMainShow();
                    if (result.State)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            int oldCount = mainViewMod.MainAlarmShowList.Count;
                            mainViewMod.MainAlarmShowList.Clear();
                            foreach (AlarmRecordEntity alarm in result.Data!)
                            {
                                AlarmModel model = new AlarmModel()
                                {
                                    Id = alarm.Id,
                                    AlarmCode = alarm.AlarmCode,
                                    Content = alarm.Content,
                                    SolutionHelp = alarm.SolutionHelp,
                                    CreateTime = alarm.CreateTime,
                                };
                                mainViewMod.MainAlarmShowList.Add(model);
                            }

                            MainPageView mainPageView = (MainPageView)(mainViewMod.PageMapping["MainPage"] as UserControl)!;
                            if (mainPageView != null)
                            {
                                var alarmDataGrid = mainPageView.AlarmDataGrid;
                                if (mainViewMod.MainAlarmShowList.Count > 0 && mainViewMod.MainAlarmShowList.Count != oldCount)
                                {
                                    mainPageView.alarmDataGrid.ScrollIntoView(mainViewMod.MainAlarmShowList[mainViewMod.MainAlarmShowList.Count - 1]);
                                }
                            }
                        });
                    }

                    DataResult<bool[]> resultAlarmPlc = PlcClient.GetPlcAlarmCode();
                    if (resultAlarmPlc.State && resultAlarmPlc.Data != null)
                    {
                        int[] trueList = resultAlarmPlc.Data.Select((value, index) => new { value, index })
                        .Where(x => x.value == true)
                        .Select(x => x.index).ToArray();
                        if (trueList != null && trueList.Length > 0)
                        {
                            // 出现报警
                            foreach (var index in trueList)
                            {
                                string ErrorCode = $"W{100 + index}";
                                LogHelper.WriteLog(LogType.Fatal, string.Empty, ErrorCode);
                            }
                        }
                    }


                    var workingInfoResult = LocalDataAccess.GetWorkingInfo();
                    if (!workingInfoResult.State)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            LogHelper.WriteLog(LogType.Fatal, workingInfoResult.Message);
                            MessageBox.Show(workingInfoResult.Message);
                            Application.Current?.Shutdown();
                            return;
                        });
                    }
                    var workingInfoData = workingInfoResult.Data!;
                    mainViewMod.WorkingInfo.FlowerNumber = workingInfoData.FlowerNumber;
                    mainViewMod.WorkingInfo.ProductionDate = DateTimeHelper.GetProductionDatetime();
                    mainViewMod.WorkingInfo.CutNumber = workingInfoData.CutNumber;
                    mainViewMod.WorkingInfo.CrystalNumber = workingInfoData.CrystalNumber;
                    mainViewMod.WorkingInfo.TheoryCounts = int.Parse(workingInfoData.TheoryCounts!);
                    mainViewMod.WorkingInfo.TotalCountFromPc = int.Parse(workingInfoData.TotalCountFromPc!);
                    mainViewMod.WorkingInfo.PositionNumber = workingInfoData.PositionNumber;
                    mainViewMod.WorkingInfo.ProductionLot = workingInfoData.ProductionLot;
                    mainViewMod.WorkingInfo.ProductionRecipe = workingInfoData.ProductionRecipe;
                    mainViewMod.WorkingInfo.RecipeImportDir = workingInfoData.RecipeImportDir;
                    mainViewMod.WorkingInfo.RecipeImportFile = workingInfoData.RecipeImportFile;
                    mainViewMod.WorkingInfo.LastCrystalNumber = workingInfoData.LastCrystalNumber;

                    // 2. 屏蔽检测模块数据的更新
                    var moduleShieldStateResult = LocalDataAccess.GetModuleShieldState();
                    if (!moduleShieldStateResult.State)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            LogHelper.WriteLog(LogType.Fatal, moduleShieldStateResult.Message);
                            MessageBox.Show(moduleShieldStateResult.Message);
                            Application.Current?.Shutdown();
                            return;
                        });
                    }

                    var moduleShieldStateData = moduleShieldStateResult.Data!;
                    Dispatcher.Invoke(() =>
                    {
                        mainViewMod.ModuleShieldedList.Clear();
                        mainViewMod.TotalModuleShieldedStates.Clear();
                        foreach (var item in moduleShieldStateData)
                        {
                            // 将所有的数据都加入到TotalModuleShieldedStates里面去
                            // 前面界面可以显示使用.
                            ModuleShieldedStateModel model = new ModuleShieldedStateModel();
                            model.ModuleName = item.ModuleName;
                            model.IsShielded = item.IsShielded;
                            mainViewMod.TotalModuleShieldedStates.Add(model);
                            if (item.IsShielded)
                            {
                                mainViewMod.ModuleShieldedList.Add(item.ModuleName!);
                            }
                        }
                        GlobalValues.ModuleIsShield = mainViewMod.ModuleShieldedList.ToList(); // 保存到全局变量中

                        //// 测试用
                        //mainViewMod.LoadIsOpen = mainViewMod.LoadIsOpen ? false : true;
                        //LocalDataAccess.UpdateWorkingInfoTotalCountFromPc();

                    });

                    if (PlcClient.PlcState.IsOnline == "已连接")
                    {
                        //UpdateBoxStateFromPlc();
                        //UpdatePlcState();
                    }

                    //更新料盒状态,防止料盒改变了最大数量之后,这里没有实时更新
                    // 这里只更新料盒存放的最大数量,主要目的是防止料盒最大数量更改之后,不用重启软件.
                    // 其实更好的做法应该是将这个变量传递给料盒设定那个对象,然后在设置之后立马通知就行.目前,我只是用了比较笨的方式
                    // 在这里实时刷新了一下
                    var boxStateResult = LocalDataAccess.GetBoxesStates();
                    if (!boxStateResult.State)
                    {

                        LogHelper.WriteLog(LogType.Fatal, boxStateResult.Message);
                        MessageBox.Show(boxStateResult.Message);
                        Application.Current?.Shutdown();
                        return;
                    }
                    var boxStateData = boxStateResult.Data!;

                    Dispatcher.Invoke(() =>
                    {
                        for (int i = 0; i < mainViewMod.BoxesStateList.Count; i++)
                        {
                            var item = boxStateData[i];
                            mainViewMod.BoxesStateList[i].CountMax = int.Parse(item.CountMax!);
                        }
                    });

                    // 3.料盒状态数据更新(这里有待商榷, 这样更新速度上会不会跟不上, 还是每次直接去更新Model这个数据, 到时候再看吧)
                    // 料盒状态更新是从PLC那边读取
                    //var boxStateResult = LocalDataAccess.GetBoxesStates();

                    //if (!boxStateResult.State)
                    //{
                    //    Dispatcher.Invoke(() =>
                    //    {
                    //        LogHelper.WriteLog(LogType.Fatal, boxStateResult.Message);
                    //        MessageBox.Show(boxStateResult.Message);
                    //        Application.Current?.Shutdown();
                    //        return;
                    //    });
                    //}
                    //var boxStateData = boxStateResult.Data!;

                    //for (int i = 0; i < boxStateData.Count; i++)
                    //{
                    //    var item = boxStateData[i];
                    //    BoxesStateModel model = new BoxesStateModel();
                    //    model.BoxNumber = item.BoxNumber;
                    //    model.LevelType = item.LevelType;
                    //    model.Count = item.Count;
                    //    model.CountMax = item.CountMax;
                    //    Dispatcher.Invoke(() =>
                    //    {
                    //        mainViewMod.BoxesStateList[i] = model;
                    //    });
                    //}

                    // 4. 当前用户登录以及系统时间更新
                    Dispatcher?.Invoke(() =>
                    {
                        mainViewMod.CurrentLoginUser = $"{GlobalValues.UserInfo!.Username}({GlobalValues.UserInfo.Role})";
                        mainViewMod.SystemTime = DateTimeHelper.GetTimeNowForSql();
                    });

                    // 5. 更新CountLevel显示的数据显示
                    DataResult<List<CrystalLevelCountEntity>> dataResult;
                    if (mainViewMod.CrystalCurrentIsChecked)
                    {
                        dataResult = LocalDataAccess.GetCrystalLevelCount(GlobalValues.CrystalNumberCurrent);
                    }
                    else
                    {
                        dataResult = LocalDataAccess.GetCrystalLevelCount(GlobalValues.LastCrystalNumber);
                    }
                    if (dataResult.State)
                    {
                        Dispatcher?.Invoke(() =>
                        {
                            mainViewMod.DetectTypeCountList.Clear();
                            foreach (var item in dataResult.Data!)
                            {
                                var temp = new DetectTypeModel();
                                temp.LevelIndex = item.LevelIndex;
                                temp.DetectedType = item.LevelType;
                                temp.DetectedCount = item.Count;
                                mainViewMod.DetectTypeCountList.Add(temp);
                            }
                        });
                    }
                });
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(LogType.Exception, ex.Message);
            }
        }

        /// <summary>
        /// 检测设备是否在线,不在线超过2次,要报警的.
        /// </summary>
        private void CheckDeviceIsOnline()
        {
            if (server02!._slaveState.ConnectedStatus != "已连接" && server02!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("尺寸"))
            {
                server02!.DisConnectedCount += 1;

                if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
                {
                    // 尺寸工位不在线报警
                    LogHelper.WriteLog(LogType.Fatal, "尺寸工位掉线", errorCode: "P01");
                    PlcClient.PlcLoadControl("Close"); // 停止上料设备运行
                }
            }
            else
            {
                if (server02!._slaveState.ConnectedStatus != "已连接")
                {
                    server02!.DisConnectedCount += 1;
                }
            }

            if (server03!._slaveState.ConnectedStatus != "已连接" && server03!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("前崩"))
            {
                server03!.DisConnectedCount += 1;

                if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
                {
                    // 崩边
                    LogHelper.WriteLog(LogType.Fatal, "崩边工位掉线", errorCode: "P05");
                    PlcClient.PlcLoadControl("Close"); // 停止上料设备运行
                }
            }
            else
            {
                if (server03!._slaveState.ConnectedStatus != "已连接")
                {
                    server03!.DisConnectedCount += 1;
                }
            }

            if (server04!._slaveState.ConnectedStatus != "已连接" && server04!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("3D"))
            {
                server04!.DisConnectedCount += 1;

                if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
                {
                    // 崩边
                    LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P02");
                    PlcClient.PlcLoadControl("Close"); // 停止主线设备运行
                }
            }
            else
            {
                if (server04!._slaveState.ConnectedStatus != "已连接")
                {
                    server04!.DisConnectedCount += 1;
                }
            }

            if (server05!._slaveState.ConnectedStatus != "已连接" && server05!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("下脏污"))
            {
                server05!.DisConnectedCount += 1;
                if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
                {
                    LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P04");
                    PlcClient.PlcLoadControl("Close"); // 停止主线设备运行
                }
            }
            else
            {
                if (server05!._slaveState.ConnectedStatus != "已连接")
                {
                    server05!.DisConnectedCount += 1;
                }
            }

            //if (server07!._slaveState.ConnectedStatus != "已连接" && server07!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("上脏污"))
            //{
            //    server07!.DisConnectedCount += 1;
            //    // 崩边
            //    if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
            //    {
            //        LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P04");
            //        PlcClient.PlcLoadControl("Close"); // 停止主线设备运行
            //    }
            //}
            //else
            //{
            //    if (server07!._slaveState.ConnectedStatus != "已连接")
            //    {
            //        server07!.DisConnectedCount += 1;
            //    }
            //}

            //if (server06!._slaveState.ConnectedStatus != "已连接" && server06!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("隐裂"))
            //{
            //    server06!.DisConnectedCount += 1;
            //    // 崩边
            //    if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
            //    {
            //        LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P03");
            //        PlcClient.PlcLoadControl("Close"); // 停止主线设备运行
            //    }
            //}
            //else
            //{
            //    if (server06!._slaveState.ConnectedStatus != "已连接")
            //    {
            //        server06!.DisConnectedCount += 1;
            //    }
            //}

            //if (server08!._slaveState.ConnectedStatus != "已连接" && server08!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("后崩"))
            //{
            //    server08!.DisConnectedCount += 1;
            //    // 崩边
            //    if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
            //    {
            //        LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P05");
            //        PlcClient.PlcLoadControl("Close"); // 停止主线设备运行
            //    }
            //}
            //else
            //{
            //    if (server08!._slaveState.ConnectedStatus != "已连接")
            //    {
            //        server08!.DisConnectedCount += 1;
            //    }
            //}

            //if (server09!._slaveState.ConnectedStatus != "已连接" && server09!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("左崩"))
            //{
            //    server09!.DisConnectedCount += 1;
            //    // 崩边
            //    if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
            //    {
            //        LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P05");
            //        PlcClient.PlcLoadControl("Close"); // 停止主线设备运行
            //    }
            //}
            //else
            //{
            //    if (server09!._slaveState.ConnectedStatus != "已连接")
            //    {
            //        server09!.DisConnectedCount += 1;
            //    }
            //}

            //if (server10!._slaveState.ConnectedStatus != "已连接" && server10!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("右崩"))
            //{
            //    server10!.DisConnectedCount += 1;
            //    // 崩边
            //    if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
            //    {
            //        LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P05");
            //        PlcClient.PlcLoadControl("Close"); // 停止主线设备运行
            //    }
            //}
            //else
            //{
            //    if (server10!._slaveState.ConnectedStatus != "已连接")
            //    {
            //        server10!.DisConnectedCount += 1;
            //    }
            //}

            if (NaponsClient!._slaveState.ConnectedStatus != "已连接" && NaponsClient!.DisConnectedCount == 2 && !GlobalValues.ModuleIsShield.Contains("电阻率"))
            {
                NaponsClient!.DisConnectedCount += 1;
                // 电阻率
                if (mainViewMod.PLCRunningState && PlcClient.PlcState.IsOnline!.Equals("已连接"))
                {
                    LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P06");
                    PlcClient.PlcLoadControl("Close"); // 停止上料设备运行
                }
            }
            else
            {
                if (NaponsClient!._slaveState.ConnectedStatus != "已连接")
                {
                    NaponsClient!.DisConnectedCount += 1;
                }
            }

            if (PlcClient.PlcState.IsOnline != "已连接" && PlcClient.DisconnectedCount == 2)
            {
                PlcClient!.DisconnectedCount += 1;
                // PLC
                LogHelper.WriteLog(LogType.Fatal, string.Empty, errorCode: "P07");
            }
            else
            {
                if (PlcClient.PlcState.IsOnline != "已连接")
                {
                    PlcClient.DisconnectedCount += 1;
                }
            }
        }

        private void UpdatePlcState()
        {
            DataResult<List<int>> result = PlcClient.GetPlcState();
            Application.Current?.Dispatcher.Invoke(() =>
            {
                if (!result.State)
                {
                    MessageBox.Show($"读取Plc设备状态异常: {result.Message}", "Plc通信异常提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }
                else
                {
                    int mainLineState = result.Data![0];
                    int loadState = result.Data![1];
                    mainViewMod.LoadIsOpen = loadState == 1 ? true : false;
                    mainViewMod.PLCRunningState = mainLineState == 1 ? true : false;
                    mainViewMod.PLCStopState = !mainViewMod.PLCRunningState;
                }
            });
        }

        /// <summary>
        /// 窗口拖动的时候
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                DragMove();
            }
        }

        private void BtnMin_Click(object sender, RoutedEventArgs e)
        {
            WindowState = WindowState.Minimized;
        }

        /// <summary>
        /// 最大化的时候,如果已经是最大化了就缩小,如果不是最大化就最大化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnMax_Click(object sender, RoutedEventArgs e)
        {
            WindowState = WindowState == WindowState.Maximized ?
                WindowState.Normal : WindowState.Maximized;
        }

        private void BtnClose_Click(object sender, RoutedEventArgs e)
        {
            Close();
            WindowClosing_Dispose();
        }

        public Command NextCrystalPrepareCommand { get; private set; }

        public Command ChangeNextCrystalCommand { get; private set; }

        private void SendClearQueueToAll()
        {
            if (!server02!.ClearResponseIsOk && server02._isAlive)
            {
                server02?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server02.pcName!, server02.cameraName!), true);
            }
            if (!server03!.ClearResponseIsOk && server03._isAlive)
            {
                server03?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server03.pcName!, server03.cameraName!), true);
            }
            if (!server04!.ClearResponseIsOk && server04._isAlive)
            {
                server04?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server04.pcName!, server04.cameraName!), true);
            }
            if (!server05!.ClearResponseIsOk && server05._isAlive)
            {
                server05?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server05.pcName!, server05.cameraName!), true);
            }
            //if (!server06!.ClearResponseIsOk && server06._isAlive)
            //{
            //    server06?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server06.pcName!, server06.cameraName!), true);
            //}
            //if (!server07!.ClearResponseIsOk && server07._isAlive)
            //{
            //    server07?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server07.pcName!, server07.cameraName!), true);
            //}
            //if (!server08!.ClearResponseIsOk && server08._isAlive)
            //{
            //    server08?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server08.pcName!, server08.cameraName!), true);
            //}
            //if (!server09!.ClearResponseIsOk && server09._isAlive)
            //{
            //    server09?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server09.pcName!, server09.cameraName!), true);
            //}
            //if (!server10!.ClearResponseIsOk && server10._isAlive)
            //{
            //    server10?.SendMsgAsync(MsgPackHelper.GetDataClearMsgSend(server10.pcName!, server10.cameraName!), true);
            //}
        }

        private void SendCrystalToAll()
        {

            if (server02!._isAlive)
            {
                server02?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server02.pcName!, server02.cameraName!), true);

            }
            if (server03!._isAlive)
            {
                server03?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server03.pcName!, server03.cameraName!), true);

            }
            if (server04!._isAlive)
            {
                server04?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server04.pcName!, server04.cameraName!), true);

            }
            if (server05!._isAlive)
            {
                server05?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server05.pcName!, server05.cameraName!), true);
            }
            //if (server06!._isAlive)
            //{
            //    server06?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server06.pcName!, server06.cameraName!), true);
            //}
            //if (server07!._isAlive)
            //{
            //    server07?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server07.pcName!, server07.cameraName!), true);
            //}
            //if (server08!._isAlive)
            //{
            //    server08?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server08.pcName!, server08.cameraName!), true);
            //}
            //if (server09!._isAlive)
            //{
            //    server09?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server09.pcName!, server09.cameraName!), true);
            ////}
            //if (server10!._isAlive)
            //{
            //    server10?.SendMsgAsync(MsgPackHelper.GetCrystalMsgSend(server10.pcName!, server10.cameraName!), true);
            //}
        }


        /// <summary>
        /// 切换下一单
        /// </summary
        private async void DoChangeNextCrystalTask(object obj)
        {
            MessageBoxResult res = MessageBox.Show("确定要切换到下一单吗 (●__●)", "操作提示", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
            if (res == MessageBoxResult.OK)
            {
                // 1. 清空视觉数据队列信号
                //DataResult dataInitRes = PowerOnDataInit();
                //if (!dataInitRes.State)
                //{
                //    return;
                //}
                //await Task.Delay(100);
                //// 3D标定按钮要做的事情

                //Do3DCalibrationTask(obj);
                server04!.Calibration3DIsOK = true;

                if (server04!.Calibration3DIsOK)
                {
                    // 标定OK之后做对应的事情. 标定OK之后再切单,这个时候应该很快就能完成.
                    // 0. 先把自己的队列清空,然后创建新的表,将上一单的数据保存好.将自己使用的字典变量全部清空.
                    DoChangeCrystalWork();
                }
                else
                {
                    MessageBox.Show($"{server04!.Calibration3DErrorInfo}", "3D标定错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

            }
        }

        private async void DoCalibration3D()
        {
            DataResult result = new DataResult();
            DataResult<ushort> resultData = new DataResult<ushort>();
            ushort status = 0;
            if (PlcCommunication.Instance.PlcState.IsOnline != "已连接")
            {
                await Task.Delay(20);
                result.Message = "PLC未连接,请检查网线连接和PLC是否已经断电";
                server04!.CloseRefresh = true;
                server04!.Calibration3DIsOK = false;
                server04!.Calibration3DErrorInfo = result.Message;
                MessageBox.Show($"{result.Message}", "标定错误", MessageBoxButton.OK, MessageBoxImage.Error);
                Dispatcher.Invoke(() => { Close(); });
                return;
            }
            // 1. 通知PLC下降挡板
            result = PlcCommunication.Instance.SwitchCrystalSignal();
            if (result.State)
            {
                for (int i = 0; i < 40; i++)
                {
                    // 2. 读取PLC挡板状态
                    resultData = PlcCommunication.Instance.GetCalBoardState();
                    if (result.State)
                    {
                        status = resultData.Data;
                        if (status == 1)
                        {
                            break;
                        }
                        else
                        {
                            await Task.Delay(50);
                            continue;
                        }
                    }
                }
                server04!.Calibration3DIsOK = false; // 先给标定状态改为false.
                server04!.CloseRefresh = false;
                if (status == 1)
                {
                    // 读取到了正确的挡板状态
                    await Task.Delay(500); // 延时0.5秒之后

                    _ = server04!.SendMsgAsync(MsgPackHelper.GetCalibration3DMsgSend());
                    for (int i = 0; i < 5; i++)
                    {
                        if (server04!.Calibration3DIsOK)
                        {
                            DataResult res = PlcCommunication.Instance.SwitchCrystalFinish();
                            if (!res.State)
                            {
                                server04!.Calibration3DErrorInfo = res.Message;
                                MessageBox.Show($"{res.Message}", "标定错误", MessageBoxButton.OK, MessageBoxImage.Error);
                                server04.CloseRefresh = true;
                                Close();
                                return;
                            }
                            else
                            {
                                // 标定成功,开始正常作业.
                            }
                        }
                        await Task.Delay(100);
                    }
                }
                else
                {
                    server04.Calibration3DErrorInfo = "PLC挡板未下落,检测下落状态为0";
                }
            }
            else
            {
                result.Message = "PLC未连接,请检查网线连接和PLC是否已经断电";
                server04!.Calibration3DErrorInfo = result.Message;
                MessageBox.Show($"{result.Message}", "标定错误", MessageBoxButton.OK, MessageBoxImage.Error);
                server04.CloseRefresh = true;
                Dispatcher.Invoke(() =>
                {
                    Close();
                    return;
                });
            }
        }

        public Command Calibration3DCommand { get; set; }
        public void Do3DCalibrationTask(object obj)
        {
            server04!.Calibration3DIsOK = false; // 标定是否OK复位.
            mainViewMod.Calibration3DStatus = "NG";
            CalibrationProgressBar progressbar = new CalibrationProgressBar(server04!, DoCalibration3D);
            progressbar.ShowDialog();

            var task = Task.Run(async delegate
            {
                await Task.Delay(100);
                Dispatcher.Invoke(() =>
                {
                    if (server04!.Calibration3DIsOK)
                    {
                        mainViewMod.Calibration3DStatus = "OK";
                        DataResult result = PlcClient.SwitchCrystalFinish();
                        if (!result.State)
                        {
                            LogHelper.WriteLog(LogType.Fatal, "PLC通信异常");
                        }
                        else
                        {
                            LogHelper.WriteLog(LogType.Info, "3D相机标定成功!");
                        }
                    }
                    else
                    {
                        DataResult result = PlcClient.SwitchCrystalFinish();
                        if (!result.State)
                        {
                            LogHelper.WriteLog(LogType.Fatal, "PLC通信异常");
                        }
                        else
                        {
                            LogHelper.WriteLog(LogType.Info, "3D相机标定成功!");
                        }
                        MessageBox.Show($"{server04.Calibration3DErrorInfo}", "标定失败提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                });
            });

        }

        /// <summary>
        /// 上位机,这里切换工单的时候要做的事情.清空数据,重新加载工单.
        /// </summary>
        private void DoChangeCrystalWork()
        {
            Task.Run(() =>
            {
                // 如果要切换的晶棒编号和当前作业的晶棒编号不相同,就要从新赋值.这里可能还要重新创建一个以晶棒编号为名字的表.
                if (GlobalValues.CrystalNumberNext != GlobalValues.CrystalNumberCurrent)
                {
                    string crystalRecordDelete = GlobalValues.LastCrystalNumber!; // 上一个晶棒编号
                    string CrystalNumberCurrent = GlobalValues.CrystalNumberCurrent!; // 当前晶棒编号
                    string CrystalNumberNext = GlobalValues.CrystalNumberNext!;   // 下一个晶棒编号
                    string quereyField = "CrystalNumber";

                    // 1. 然后将这些新的消息更新到WorkingInfo表中去,包括那些晶棒编号之类的.
                    DataResult res = UpdateWorkingInfo();
                    if (!res.State)
                    {
                        MessageBox.Show($"{res.Message}", "切换下一单失败提示框", MessageBoxButton.OK, MessageBoxImage.Error);
                        return;
                    }


                    // 2. 创建新的晶棒编号,并且实时的显示到界面上去.
                    TableManager.CreateWaferDetectedDetailTable(GlobalValues.CrystalNumberNext!);

                    // 如果要删除的晶棒编号和当前的以及下一个不相同时再删除
                    if (!crystalRecordDelete.Equals(CrystalNumberCurrent) && !crystalRecordDelete.Equals(CrystalNumberNext))
                    {
                        // 3. 将多余上上一个的晶棒编号删除掉.
                        LocalDataAccess.DeleteDataByFeild(TableNames.CrystalLevelCountTb, quereyField, crystalRecordDelete);
                    }

                    //4. 将上一单的晶棒信息(就是当前正在作业的工单信息)保存到历史记录里面去.
                    DataResult result = LocalDataAccess.SaveCrystalRecordByCrystalNumber(CrystalNumberCurrent);
                    if (!result.State)
                    {
                        LogHelper.WriteLog(LogType.Fatal, result.Message);
                    }



                    // 5. 流水号和实际片数重置
                    //DataResult plcRes = PlcClient.ResetWaferIdAndRealCount();
                    //if (!plcRes.State)
                    //{
                    //    LogHelper.WriteLog(LogType.Fatal, "PLC通信异常,请检查PLC连接,重置流水号和实际片数失败");
                    //}

                }
                // 1. 晶棒工单初始化
                Dispatcher.Invoke((() =>
                {
                    mainViewMod.InitRecipe();
                }));
                // 2. 发送将要作业的晶棒编号
                SendCrystalToAll();
                // 2. 第二步就是一些全局变量的清空
                GlobalValues.WaferIdLevelDictionary.Clear();
                GlobalValues.WaferIdFromPcDictionary.Clear();
                GlobalValues.WaferIdDateSummary.Clear();
                mainViewMod.NextCrystalIsOK = false;
                GlobalValues.CrystalFinishState = false; //将晶棒完成状态置为false.

                //3. 创建目录
                FileOperateHelper.CreateSummaryDir();

                // 4. 如果上料状态是关闭的,要打开上料,如果上料停止了,就打开上料.
                if (!mainViewMod.LoadIsOpen)
                {
                    PlcClient.PlcLoadControl("Open");
                }
            });
        }

        private DataResult UpdateWorkingInfo()
        {
            DataResult result = new DataResult();
            try
            {
                List<string> updateFields = new List<string>();
                List<string> updateVals = new List<string>();

                updateFields.Add("LastCrystalNumber");
                updateVals.Add(GlobalValues.CrystalNumberCurrent!); // 前一晶棒.
                GlobalValues.LastCrystalNumber = GlobalValues.CrystalNumberCurrent!;

                updateFields.Add("CrystalNumber");
                updateVals.Add(GlobalValues.CrystalNumberNext!);
                GlobalValues.CrystalNumberCurrent = GlobalValues.CrystalNumberNext!;

                updateFields.Add("FlowerNumber");
                updateVals.Add(GlobalValues.FlowerNumberNext!);
                GlobalValues.FlowerNumber = GlobalValues.FlowerNumberNext!;

                updateFields.Add("CutNumber");
                updateVals.Add(GlobalValues.CrystalNumberNext!);
                GlobalValues.CutNumber = GlobalValues.CrystalNumberNext;

                updateFields.Add("TheoryCounts");
                updateVals.Add(GlobalValues.TheoryNumberNext.ToString()!);


                updateFields.Add("ProductionRecipe");
                updateVals.Add(GlobalValues.ProductionRecipeName);


                updateFields.Add("PositionNumber");
                updateVals.Add(GlobalValues.PostionNumberNext!);
                GlobalValues.PositionNumber = GlobalValues.PostionNumberNext!;

                updateFields.Add("ProductionLot");
                updateVals.Add(GlobalValues.ProductionLotNext!);
                GlobalValues.ProductionLot = GlobalValues.ProductionLotNext!;
                result = LocalDataAccess.UpdateWorkingInfo(updateFields, updateVals);
                return result;
            }

            catch (Exception ex)
            {
                result.Message = ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!);
            }
            return result;
        }

        /// <summary>
        /// 输入下一单
        /// </summary>
        private void DoNextCrystalPrepareTask(object obj)
        {
            GlobalValues.CrystalNumberNext = $"JY-{DateTime.Now.Year}-{DateTime.Now.Month}"; // 先赋值为默认值
            InputNextCrystalWindow prepareInputWindow = new InputNextCrystalWindow();
            prepareInputWindow.Owner = mainWindow;
            prepareInputWindow.ShowDialog();
            if (!string.IsNullOrEmpty(GlobalValues.CrystalNumberNext))
            {
                // 输入下一单成功
                mainViewMod.NextCrystalIsOK = true;
            }
        }




        // 当前晶棒统计命令,用来切换晶棒统计结果
        public Command CrystalCurrentRadioCommand { get; set; }

        private void DoSwitchCrystalShowTask(object obj)
        {
            if (obj != null)
            {
                DataResult<List<CrystalLevelCountEntity>> dataResult;
                // 这里切换的时候,先按照等级降序去更新.
                if (mainViewMod.CrystalCurrentIsChecked)
                {
                    dataResult = LocalDataAccess.GetCrystalLevelCount(GlobalValues.CrystalNumberCurrent);
                }
                else
                {
                    dataResult = LocalDataAccess.GetCrystalLevelCount(GlobalValues.LastCrystalNumber);
                }
                if (dataResult.State)
                {
                    mainViewMod.DetectTypeCountList.Clear();
                    foreach (var item in dataResult.Data!)
                    {
                        var temp = new DetectTypeModel();
                        temp.LevelIndex = item.LevelIndex;
                        temp.DetectedType = item.LevelType;
                        temp.DetectedCount = item.Count;
                        mainViewMod.DetectTypeCountList.Add(temp);
                    }
                }
            }
        }
    }
}
